import { EnemyType } from "../Constant/Constant"
import EnemyControl from "../Control/EnemyControl"

export interface EnemyPrefab {
    type: EnemyType,
    prefab: cc.Prefab
}

/**
 * 敌方飞机工厂(静态单例)
 * 用于创建不同类型的敌机，简化敌机创建过程
 * 使用节点池缓存敌机
 */
export default class EnemyFactory {

    private static _prefabMap: Map<EnemyType, cc.Prefab> = new Map()
    private static _poolMap: Map<EnemyType, cc.NodePool> = new Map()

    private constructor() { }

    /**
     * 初始化，保存敌机预制体
     * @param enemy1 
     * @param enemy2 
     * @param enemy3 
     */
    public static init(enemys: EnemyPrefab[]) {
        this._prefabMap = new Map()
        this._poolMap = new Map()
        enemys.forEach((enemyPrefab) => {
            this._prefabMap.set(enemyPrefab.type, enemyPrefab.prefab)
            this._poolMap.set(enemyPrefab.type, new cc.NodePool(EnemyControl))
            // console.log(`[EnemyFactory] enemyPrefab.type:`, enemyPrefab.type)
        })
    }

    /**
     * 根据type创建一个敌机，并且自动初始化（节点可能会从节点池中获取）
     * @param type 敌机类型
     * @returns 敌机节点对象
     */
    public static create(type: EnemyType, parent?: cc.Node): cc.Node {
        // error
        if (!this._prefabMap.has(type)) {
            throw new Error('init()初始化时未包含该type类型的prefab预制体')
        }
        if (!this._poolMap.has(type)) {
            throw new Error(`_enemyPoolMap不存在该type{${type}}类型`)
        }

        let enemy: cc.Node = null
        // 获取对象池
        const pool = this._poolMap.get(type)

        if (pool.size() > 0) {
            enemy = pool.get()
            // console.log(`[EnemyFactory] enemy nodes from the pool`)
        } else {
            // 对象池为空，instantiate创建节点
            const prefab = this._prefabMap.get(type)
            enemy = cc.instantiate(prefab)
            // console.log(`[EnemyFactory] enemy nodes from the cc.instantiate(prefab)`)
        }

        // 初始化敌机
        enemy.getComponent(EnemyControl).init(type)
        if (parent) { enemy.setParent(parent) }
        return enemy
    }

    /**
     * 回收敌机节点
     * @param enemyNode 
     */
    public static recycle(enemyNode: cc.Node) {
        const comp = enemyNode.getComponent(EnemyControl)
        if (!comp) { return }
        if (!this._poolMap.has(comp.type)) {
            console.warn(`_enemyPoolMap不存在该type{${comp.type}}类型`)
            return
        }

        if (this._poolMap.has(comp.type)) {
            const pool = this._poolMap.get(comp.type)
            pool.put(enemyNode) // 节点会从父节点上移除
        }
    }
}
